package jp.sourceforge.akjrcp.potrace;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;

import jp.sourceforge.akjrcp.ui.GenericParameters;
import jp.sourceforge.akjrcp.util.ColorUtils;
import jp.sourceforge.akjrcp.util.directorybased.DirectoryBasedCommand;
import jp.sourceforge.akjrcp.util.directorybased.DirectoryBasedCommandExecuter;
import jp.sourceforge.akjrcp.util.directorybased.DirectoryBasedRuntimeCommand;
import jp.sourceforge.akjrcp.util.directorybased.PbmToImageCommand;
import jp.sourceforge.akjrcp.util.directorybased.PgmToImageCommand;
import jp.sourceforge.akjrcp.util.directorybased.PostScriptToImageCommand;
import jp.sourceforge.akjrcp.util.directorybased.RenameCommand;

public class PotraceExecuter extends DirectoryBasedCommandExecuter{

	private GenericParameters genericParameters;
	private String mkBitmapPath;
	private String potracePath;
	//private File deleteBmp;
	private List<File> temporaryFiles=new ArrayList<File>();
	private boolean execMkbitmap;
	private boolean execPotrace;
	
	private File finalExported;
	
	private boolean mixImage;
	private String bgColor="#ffffff";//white
	private float imageTransparent=1.0f;
	private float lineTransparent=1.0f;
	private int blur=1;
	public float getImageTransparent() {
		return imageTransparent;
	}

	public void setImageTransparent(float imageTransparent) {
		this.imageTransparent = imageTransparent;
	}

	public float getLineTransparent() {
		return lineTransparent;
	}

	public void setLineTransparent(float lineTransparent) {
		this.lineTransparent = lineTransparent;
	}

	public boolean isExecMkbitmap() {
		return execMkbitmap;
	}

	public void setExecMkbitmap(boolean execMkbitmap) {
		this.execMkbitmap = execMkbitmap;
	}

	public boolean isExecPotrace() {
		return execPotrace;
	}

	public void setExecPotrace(boolean execPotrace) {
		this.execPotrace = execPotrace;
	}

	public String getPotracePath() {
		return potracePath;
	}

	public void setPotracePath(String potracePath) {
		this.potracePath = potracePath;
	}

	@Override
	protected void inFinallyAction(File file, File output) {
		for(int i=0;i<temporaryFiles.size();i++){
			File tmp=temporaryFiles.get(i);
			if(tmp!=null){
				tmp.delete();
			}
		}
	}

	@Override
	protected void processReturnValue(int value) {
		if(value!=0){
		log.warn("error-exit:"+value);
		}
	}

	private boolean isSupportedInput(String input){
		if(input.toLowerCase().endsWith(".bmp")){
			return true;
		}
		if(input.toLowerCase().endsWith(".pbm")){
			return true;
		}
		if(input.toLowerCase().endsWith(".pgm")){
			return true;
		}
		if(input.toLowerCase().endsWith(".ppm")){
			return true;
		}
		return false;
	}
	@Override
	protected DirectoryBasedCommand[] toCommand(File input, File output) {
		List<DirectoryBasedCommand> cList=new ArrayList<DirectoryBasedCommand>();
		File bmpFile;
		int width=0;
		int height=0;
		//any image file to bmp
		BufferedImage bimage=null;
		try {
			//need size
			bimage = ImageIO.read(input);
			width=bimage.getWidth();
			height=bimage.getHeight();
		} catch (IOException e1) {
			e1.printStackTrace();
			return null;
		}
		
		if(isSupportedInput(input.getName())){
			bmpFile=input;
		}else{
			try {
				bmpFile=File.createTempFile("tmp", ".bmp");
				temporaryFiles.add(bmpFile);
				
				//log.info(bimage.getWidth()+","+bimage.getHeight());
				if(bimage==null){
					log.warn("input image is null");
					return null;
				}
				BufferedImage tmpImage=new BufferedImage(bimage.getWidth(),bimage.getHeight(),BufferedImage.TYPE_INT_RGB);
				tmpImage.getGraphics().drawImage(bimage, 0,0,null);
				//FileOutputStream fout=new FileOutputStream(bmpFile);
				ImageIO.write(tmpImage,"bmp",bmpFile);
				//fout.flush();
				//fout.close();
			} catch (IOException e) {
				
				e.printStackTrace();
				return null;
			}
		}
		
		File potraceInput;
		if(execMkbitmap){
		try {
			
				potraceInput=File.createTempFile("tmp", ".pbm");//pbm or pgm
				temporaryFiles.add(potraceInput);
				

				
				String[] mkCommand=MkBitmapUtils.toCommand(mkBitmapPath, genericParameters, bmpFile.getAbsolutePath(), potraceInput.getAbsolutePath());
				cList.add(new DirectoryBasedRuntimeCommand("mkbitmap",mkCommand));
				String scale=genericParameters.getParameters().get(MkBitmapUtils.KEY_HEADER+"_s");
				//scale resize image
				int s;
				if(scale.equals("")){
					s=2;
				}else{
					s=(int) Double.parseDouble(scale);
				}
				//width*=s; //TODO another param
				//height*=s;
		
				if(!execPotrace){
					if(outputExtension.equals("png") ||outputExtension.equals("jpg")||outputExtension.equals("bmp")){
						if(genericParameters.getParameters().get(MkBitmapUtils.KEY_HEADER+"_g")!=null){
						cList.add(new PgmToImageCommand(potraceInput,output,outputExtension));	
						}else{
						cList.add(new PbmToImageCommand(potraceInput,output,outputExtension));
						}
					}else{
						cList.add(new RenameCommand(potraceInput,output));
					}
				}
			
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
		}else{
		potraceInput=bmpFile;
		}
		
		
		if(execPotrace){
			try {
				
				if(outputExtension.equals("png") ||outputExtension.equals("jpg")||outputExtension.equals("bmp")){
					genericParameters.set("P", width+"x"+height);//need for image
					finalExported=File.createTempFile("tmp", ".ps");//it depends on type
					temporaryFiles.add(finalExported);
					String[] potraceCommand=PotraceUtils.toCommand(potracePath, genericParameters, potraceInput.getAbsolutePath(), finalExported.getAbsolutePath());
					cList.add(new DirectoryBasedRuntimeCommand("potrace",potraceCommand));
					PostScriptToImageCommand command=new PostScriptToImageCommand(finalExported,output,outputExtension);
					//if need image.load it TODO;
					if(mixImage){
						command.setImage(bimage);
					}
					//log.infoline"+lineTransparent);
					command.setLineTransparent(lineTransparent);
					//log.infoimage"+imageTransparent);
					command.setImageTransparent(imageTransparent);
					//log.infobgColor"+bgColor+","+ColorUtils.hexToInt(bgColor));
					command.setBackgroundColor(ColorUtils.hexToInt(bgColor));
					command.setBlur(blur);
					command.setWidth(width);
					command.setHeight(height);
					cList.add(command);
				}else{
					//directly export
					String backend="postscript";
					if(outputExtension.equals("ps")){
						backend="postscript";
					}else if(outputExtension.equals("eps")){
						backend="eps";
					}else if(outputExtension.equals("svg")){
						backend="svg";
					}else if(outputExtension.equals("pdf")){
						backend="pdf";
					}else if(outputExtension.equals("pgm")){
						backend="pgm";
					}
					genericParameters.set("b", backend);
					String[] potraceCommand=PotraceUtils.toCommand(potracePath, genericParameters, potraceInput.getAbsolutePath(), output.getAbsolutePath());
					cList.add(new DirectoryBasedRuntimeCommand("potrace",potraceCommand));	
				}
				
				
				
				
			} catch (IOException e) {
				e.printStackTrace();
				return null;
			}
			}else{
			//
			finalExported=potraceInput;
			}
		
		
		return (DirectoryBasedCommand[]) cList.toArray(new DirectoryBasedCommand[cList.size()]);
	}

	@Override
	protected void afterExecuteCommand(DirectoryBasedCommand command) {
		
		
	}

	@Override
	protected void beforeExecuteCommand(DirectoryBasedCommand command) {
		
	}

	public GenericParameters getGenericParameters() {
		return genericParameters;
	}

	public void setGenericParameters(GenericParameters genericParameters) {
		this.genericParameters = genericParameters;
		if(genericParameters.getParameters().get("MKBITMAP_USE")!=null){
			execMkbitmap=true;
		}
		
		if(genericParameters.getParameters().get("POTRACE_USE")!=null){
			execPotrace=true;
		}
	}

	public String getMkBitmapPath() {
		return mkBitmapPath;
	}

	public void setMkBitmapPath(String mkBitmapPath) {
		this.mkBitmapPath = mkBitmapPath;
	}

	public boolean isMixImage() {
		return mixImage;
	}

	public void setMixImage(boolean mixImage) {
		this.mixImage = mixImage;
	}

	public String getBgColor() {
		return bgColor;
	}

	public void setBgColor(String bgColor) {
		this.bgColor = bgColor;
	}

	public int getBlur() {
		return blur;
	}

	public void setBlur(int bluar) {
		this.blur = bluar;
	}

	

}
